Common Lisp includes a complex and powerful
“declaration” mechanism that allows you to give the
compiler special hints about the types of data that will be
stored in particular variables, and about the ways those
variables and functions will be used. This package defines
versions of all the Common Lisp declaration forms:
declare, locally,
proclaim, declaim, and
the.
Most of the Common Lisp declarations are not currently useful
in Emacs Lisp, as the byte-code system provides little
opportunity to benefit from type information, and
special declarations are redundant in a fully
dynamically-scoped Lisp. A few declarations are meaningful when
the optimizing byte compiler is being used, however. Under the
earlier non-optimizing compiler, these declarations will
effectively be ignored.
This function records a “global” declaration specified by decl-spec. Since
proclaimis a function, decl-spec is evaluated and thus should normally be quoted.
This macro is like
proclaim, except that it takes any number of decl-spec arguments, and the arguments are unevaluated and unquoted. Thedeclaimmacro also puts an(eval-when (compile load eval) ...)around the declarations so that they will be registered at compile-time as well as at run-time. (This is vital, since normally the declarations are meant to influence the way the compiler treats the rest of the file that contains thedeclaimform.)
This macro is used to make declarations within functions and other code. Common Lisp allows declarations in various locations, generally at the beginning of any of the many “implicit
progns” throughout Lisp syntax, such as function bodies,letbodies, etc. Currently the only declaration understood bydeclareisspecial.
In this package,
locallyis no different fromprogn.
Type information provided by
theis ignored in this package; in other words,(thetype form)is equivalent to form. Future versions of the optimizing byte-compiler may make use of this information.For example,
mapcarcan map over both lists and arrays. It is hard for the compiler to expandmapcarinto an in-line loop unless it knows whether the sequence will be a list or an array ahead of time. With(mapcar 'car (the vector foo)), a future compiler would have enough information to expand the loop in-line. For now, Emacs Lisp will treat the above code as exactly equivalent to(mapcar 'car foo).
Each decl-spec in a proclaim,
declaim, or declare should be a list
beginning with a symbol that says what kind of declaration it is.
This package currently understands special,
inline, notinline,
optimize, and warn declarations. (The
warn declaration is an extension of standard Common
Lisp.) Other Common Lisp declarations, such as type
and ftype, are silently ignored.
specialspecial declarations
are only advisory. They simply tell the optimizing byte
compiler that the specified variables are intentionally being
referred to without being bound in the body of the function.
The compiler normally emits warnings for such references,
since they could be typographical errors for references to
local variables.
The declaration (declare (special
var1 var2)) is equivalent
to (defvar var1) (defvar
var2) in the optimizing compiler, or
to nothing at all in older compilers (which do not warn for
non-local references).
In top-level contexts, it is generally better to write
(defvar var) than
(declaim (special var)),
since defvar makes your intentions clearer. But
the older byte compilers can not handle defvars
appearing inside of functions, while (declare
(special var)) takes care to
work correctly with all compilers.
inlineinline decl-spec lists one or
more functions whose bodies should be expanded
“in-line” into calling functions whenever the
compiler is able to arrange for it. For example, the Common
Lisp function cadr is declared
inline by this package so that the form
(cadr x) will expand
directly into (car (cdr
x)) when it is called in user
functions, for a savings of one (relatively expensive)
function call.
The following declarations are all equivalent. Note that
the defsubst form is a convenient way to define
a function and declare it inline all at once.
(declaim (inline foo bar))
(eval-when (compile load eval) (proclaim '(inline foo bar)))
(defsubst foo (...) ...) ; instead of defun
Please note: this declaration remains in effect after the containing source file is done. It is correct to use it to request that a function you have defined should be inlined, but it is impolite to use it to request inlining of an external function.
In Common Lisp, it is possible to use (declare
(inline ...)) before a particular call to a function
to cause just that call to be inlined; the current byte
compilers provide no way to implement this, so (declare
(inline ...)) is currently ignored by this
package.
notinlinenotinline declaration lists functions
which should not be inlined after all; it cancels a previous
inline declaration.optimizeThe word optimize is followed by any number
of lists like (speed 3) or (safety
2). Common Lisp defines several optimization
“qualities”; this package ignores all but
speed and safety. The value of a
quality should be an integer from 0 to 3, with 0 meaning
“unimportant” and 3 meaning “very
important.” The default level for both qualities is
1.
In this package, with the optimizing compiler, the
speed quality is tied to the
byte-compile-optimize flag, which is set to
nil for (speed 0) and to
t for higher settings; and the
safety quality is tied to the
byte-compile-delete-errors flag, which is set to
t for (safety 3) and to
nil for all lower settings. (The latter flag
controls whether the compiler is allowed to optimize out code
whose only side-effect could be to signal an error, e.g.,
rewriting (progn foo bar) to bar
when it is not known whether foo will be bound
at run-time.)
Note that even compiling with (safety 0), the
Emacs byte-code system provides sufficient checking to
prevent real harm from being done. For example, barring
serious bugs in Emacs itself, Emacs will not crash with a
segmentation fault just because of an error in a
fully-optimized Lisp program.
The optimize declaration is normally used in
a top-level proclaim or declaim in
a file; Common Lisp allows it to be used with
declare to set the level of optimization locally
for a given form, but this will not work correctly with the
current version of the optimizing compiler. (The
declare will set the new optimization level, but
that level will not automatically be unset after the
enclosing form is done.)
warnwarn is
followed by any number of “warning qualities,”
similar in form to optimization qualities. The currently
supported warning types are redefine,
callargs, unresolved, and
free-vars; in the current system, a value of 0
will disable these warnings and any higher value will enable
them. See the documentation for the optimizing byte compiler
for details.